// sswinos.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "winos.h"
#include <atlbase.h>

_SSL_BEGIN
_SSWINOSL_BEGIN

void win_center_window(
	ss_in_ HWND parent_win_h,
	ss_in_ SIZE win_size,
	ss_out_ RECT &win_rt
	)
{
	RECT rt = {0};
	if(!::GetWindowRect(parent_win_h, &rt))
	{
		SetRectEmpty(&rt);
	}

	if(::IsRectEmpty(&rt))
	{
		MONITORINFO monitor_info = { 0 };
		monitor_info.cbSize = sizeof(monitor_info);
		::GetMonitorInfo(::MonitorFromWindow(::GetDesktopWindow(), MONITOR_DEFAULTTOPRIMARY), &monitor_info);
		rt = monitor_info.rcWork;
	}

	POINT pt;
	pt.x = rt.left + (rt.right - rt.left) / 2;
	pt.y = rt.top + (rt.bottom - rt.top) / 2;
	pt.x = pt.x - win_size.cx / 2;
	pt.y = pt.y - win_size.cy / 2;

	RECT rt_all_screen;
	if (::GetSystemMetrics(SM_CMONITORS) == 0)
	{
		// Multiple display monitors not supported.
		rt_all_screen.left = 0;
		rt_all_screen.top = 0;
		rt_all_screen.right = ::GetSystemMetrics(SM_CXSCREEN);
		rt_all_screen.bottom = ::GetSystemMetrics(SM_CYSCREEN);
	}
	else
	{
		// Multiple display monitors supported.
		rt_all_screen.left = ::GetSystemMetrics(SM_XVIRTUALSCREEN);
		rt_all_screen.top =  ::GetSystemMetrics(SM_YVIRTUALSCREEN);
		rt_all_screen.right = ::GetSystemMetrics(SM_XVIRTUALSCREEN) + ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
		rt_all_screen.bottom = ::GetSystemMetrics(SM_YVIRTUALSCREEN) + ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
	}

	if(pt.x < rt_all_screen.left)
		pt.x = rt_all_screen.left;
	else if(pt.x + win_size.cx > rt_all_screen.right)
		pt.x = rt_all_screen.right - win_size.cx;

	if(pt.y < rt_all_screen.top)
		pt.y = rt_all_screen.top;
	else if(pt.y + win_size.cy > rt_all_screen.bottom)
		pt.y = rt_all_screen.bottom - win_size.cy;

	win_rt.left = pt.x;
	win_rt.top = pt.y;
	win_rt.right = win_rt.left + win_size.cx;
	win_rt.bottom = win_rt.top + win_size.cy;
}

bool os_isxp()
{
	OSVERSIONINFOEX ver_info = { sizeof(ver_info) };
	if(!GetVersionEx((OSVERSIONINFO*)&ver_info))
		return true;
	return (ver_info.dwMajorVersion < 6);
}

bool is_valid_address(
	const void* p,
	size_t bytes,
	bool f_read_write  /*= true*/
	)
{
	return ATL::AtlIsValidAddress(p, bytes, f_read_write ? TRUE : FALSE) ? true : false;
}

HGLOBAL copy_global_memory(HGLOBAL dest_h, HGLOBAL src_h)
{
	SS_ASSERT(src_h != NULL);

	// make sure we have suitable hDest
	SIZE_T src_size = ::GlobalSize(src_h);
	if (dest_h == NULL)
	{
		dest_h = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, src_size);
		if (dest_h == NULL)
			return NULL;
	}
	else if (src_size > ::GlobalSize(dest_h))
	{
		// hDest is not large enough
		return NULL;
	}

	// copy the bits
	LPVOID src_ptr = ::GlobalLock(src_h);
	LPVOID dest_ptr = ::GlobalLock(dest_h);
	SS_ASSERT(dest_ptr != NULL);
	SS_ASSERT(src_ptr != NULL);
	memcpy_s(dest_ptr, (ULONG)::GlobalSize(dest_h), src_ptr, (ULONG)src_size);
	::GlobalUnlock(dest_h);
	::GlobalUnlock(src_h);

	// success -- return hDest
	return dest_h;
}

LPSTREAM create_memory_stream()
{
	LPSTREAM stream = NULL;
	if(FAILED(CreateStreamOnHGlobal(NULL, TRUE, &stream)))
		return NULL;
	return stream;
}

_SSWINOSL_END
_SSL_END
